package com.sugon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.dao.*;
import com.sugon.entity.*;
import com.sugon.modules.sparepart.consts.SparePartsConsumeType;
import com.sugon.modules.sparepart.service.ISparepartStoreManager;
import com.sugon.service.*;
import com.sugon.utils.ShiroUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * 备件耗用记录Service实现类
 *
 * @author sugon
 * @date 2022-08-17 09:11:28
 */
@Service("sparePartConsumRecordService")
public class SparePartConsumRecordServiceImpl implements SparePartConsumRecordService {

    @Autowired
    private SparePartConsumRecordDao sparePartConsumRecordDao;
    @Resource
    private ISparepartStoreManager sparepartStoreManager;
    @Autowired
    private SpareStorePosService spareStorePosService;
    @Autowired
    private SparePartDao sparePartDao;
    @Autowired
    private SparePartTransactionRecordDao sparePartTransactionRecordDao;
    @Resource
    private MaterialRecordDao materialRecordDao;
    @Resource
    private DevRepairRecordService devRepairRecordService;
    @Resource
    private DevMaintenanceTicketService devPmTicketService;
    @Resource
    private MaterialRecordService materialRecordService;
    @Resource
    private ScarpListService scarpListService;
    @Resource
    private ScarpListDao scarpListDao;

    @Override
    public SparePartConsumRecordEntity queryObject(String id) {
        return sparePartConsumRecordDao.queryObject(id);
    }

    @Override
    public List<SparePartConsumRecordEntity> queryList(SparePartConsumRecordEntity queryParam) {
        return queryList(BeanUtil.beanToMap(queryParam));
    }

    @Override
    public List<SparePartConsumRecordEntity> queryList(String type, String businessId) {
        Map<String, Object> param = MapUtil.newHashMap();
        param.put("type", type);
        param.put("businessId", businessId);
        return queryList(param);
    }

    @Override
    public List<SparePartConsumRecordEntity> queryList(Map<String, Object> map) {
        return sparePartConsumRecordDao.queryList(map);
    }

    @Override
    public int queryTotal(Map<String, Object> map) {
        return sparePartConsumRecordDao.queryTotal(map);
    }

    @Override
    public int save(SparePartConsumRecordEntity sparePartConsumRecord) {
        sparePartConsumRecord.setId(RandomUtil.randomString(32));
        sparePartConsumRecord.setGmtCreate(DateUtil.date());
        if (StrUtil.isEmpty(sparePartConsumRecord.getCreateUser())) {
            sparePartConsumRecord.setCreateUser(ShiroUtils.getUserId());
        }
        sparePartConsumRecord.setWorkshop(ShiroUtils.getWorkshop());
        return sparePartConsumRecordDao.save(sparePartConsumRecord);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean modifyConsumeNum(SparePartConsumRecordEntity consumeRecord) {
        int updateNum = update(consumeRecord);
        Assert.isTrue(updateNum > 0);
        /*
            设备维修关联的领料是从领料明细关联的，即已经出库完毕了，不需要再次出库
            其它场景的领料如果库位不为空，那么需要重新出库
         */
        // 由于设备维修领料关联的是领料明细。那么更新完数目后需要重新计算下更换数
        if (StrUtil.equalsAny(consumeRecord.getType(), SparePartsConsumeType.REPAIR.name(), SparePartsConsumeType.MAINTENANCE.name())) {
            // 重新更新下领料明细数
            materialRecordDao.realtimeUpdateReplaceNum(consumeRecord.getMaterialRecordId());
            // 当领用数目大于0时，生成报废记录
            if(consumeRecord.getNum() > 0){
                scarpListService.doScrap(consumeRecord);
            }
        } else {
            // 如果是从库位进行的领料，需要自动出库且生成备件耗用出库记录
            if (StrUtil.isNotEmpty(consumeRecord.getPosId())) {
                sparepartStoreManager.consumeStockOut(consumeRecord);
            }
        }
        return true;
    }

    @Override
    public void generateByRepairMaterial(MaterialBaseEntity materialBase) {
        // 获取维修工单
        DevRepairRecordEntity repairRecord = devRepairRecordService.queryObjectByRepairCode(materialBase.getJobCode());
        if (repairRecord == null) {
            return;
        }
        // 获取领料明细
        List<MaterialRecordEntity> materialRecords = materialRecordService.queryByMater(materialBase.getId());
        if (CollectionUtil.isEmpty(materialRecords)) {
            return;
        }
        SparePartConsumRecordEntity consumeRecord;
        for (MaterialRecordEntity materialRecord : materialRecords) {
            consumeRecord = new SparePartConsumRecordEntity();
            consumeRecord.setType(SparePartsConsumeType.REPAIR.name());
            consumeRecord.setBusinessId(repairRecord.getId());
            consumeRecord.setSparePartId(materialRecord.getSpareId());
            consumeRecord.setNum(materialRecord.getActualNum());
            consumeRecord.setPosId(materialRecord.getPostionId());
            consumeRecord.setWorkshop(materialBase.getDeptId());
            consumeRecord.setTicketCode(repairRecord.getRepairCode());
            consumeRecord.setMaterialRecordId(materialRecord.getId());
            consumeRecord.setDevId(repairRecord.getDevId());
            if (save(consumeRecord) > 0) {
                // 更新下领料明细的换用数
                materialRecordDao.realtimeUpdateReplaceNum(consumeRecord.getMaterialRecordId());
            }
        }
    }

    @Override
    public void generateByPmMaterial(MaterialBaseEntity materialBase) {
        // 获取PM工单
        DevMaintenanceTicketEntity devPmTicket = devPmTicketService.queryObjectByRepairCode(materialBase.getJobCode());
        if (devPmTicket == null) {
            return;
        }
        // 获取领料明细
        List<MaterialRecordEntity> materialRecords = materialRecordService.queryByMater(materialBase.getId());
        if (CollectionUtil.isEmpty(materialRecords)) {
            return;
        }
        SparePartConsumRecordEntity consumeRecord;
        for (MaterialRecordEntity materialRecord : materialRecords) {
            consumeRecord = new SparePartConsumRecordEntity();
            consumeRecord.setType(SparePartsConsumeType.MAINTENANCE.name());
            consumeRecord.setBusinessId(devPmTicket.getId());
            consumeRecord.setSparePartId(materialRecord.getSpareId());
            consumeRecord.setNum(materialRecord.getActualNum());
            consumeRecord.setPosId(materialRecord.getPostionId());
            consumeRecord.setWorkshop(materialBase.getDeptId());
            consumeRecord.setTicketCode(devPmTicket.getRepairCode());
            consumeRecord.setMaterialRecordId(materialRecord.getId());
            consumeRecord.setDevId(devPmTicket.getDevId());
            if (save(consumeRecord) > 0) {
                // 更新下领料明细的换用数
                materialRecordDao.realtimeUpdateReplaceNum(consumeRecord.getMaterialRecordId());
            }
        }
    }

    @Override
    public Integer statTotalNum(String posId, String month) {
        Integer totalNum = sparePartConsumRecordDao.statTotalNum(posId, month);
        return totalNum == null ? 0 : totalNum;
    }

    @Override
    public int update(SparePartConsumRecordEntity sparePartConsumRecord) {
        sparePartConsumRecord.setGmtCreate(DateUtil.date());
        if (StrUtil.isEmpty(sparePartConsumRecord.getCreateUser())) {
            sparePartConsumRecord.setCreateUser(ShiroUtils.getUserId());
        }
        return sparePartConsumRecordDao.update(sparePartConsumRecord);
    }

    @Override
    public int delete(String id) {
        return sparePartConsumRecordDao.deleteBatch(new String[]{id});
    }

    @Override
    public int delete(String type, String businessId) {
        int rows = 0;
        // 如果有换件记录的话，删除下
        Map<String, Object> param = MapUtil.newHashMap();
        param.put("type", type);
        param.put("businessId", businessId);
        List<SparePartConsumRecordEntity> consumeRecords = queryList(param);
        if (CollectionUtil.isNotEmpty(consumeRecords)) {
            for (SparePartConsumRecordEntity consumeRecord : consumeRecords) {
                rows += delete(consumeRecord.getId());
            }
        }
        return rows;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteBatch(String[] ids) {
        for (String id : ids) {
            SparePartConsumRecordEntity consumeRecord = queryObject(id);
            if (consumeRecord == null) {
                continue;
            }
            if (delete(id) > 0) {
                SparePartEntity spareParts = sparePartDao.queryObject(consumeRecord.getSparePartId());
                Assert.notNull(spareParts);
                // 设备维修换件以外的场景：如果库位ID存在，则表示出库。删除时需要重新计算下库存信息
                if (!StrUtil.equalsAny(consumeRecord.getType(), SparePartsConsumeType.REPAIR.name(), SparePartsConsumeType.MAINTENANCE.name())) {
                    if (StrUtil.isNotEmpty(consumeRecord.getPosId())) {
                        // 1、实时更新备件库位的库存和锁定库存数
                        spareStorePosService.realtimeUpdateStorePosStock(consumeRecord.getPosId());
                        // 2、实时更新备件库存数
                        sparePartDao.realtimeUpdateStock(spareParts.getPartCode());
                    }
                } else {
                    // 删除后重新计算下领料明细的可用数
                    materialRecordDao.realtimeUpdateReplaceNum(consumeRecord.getMaterialRecordId());
                }
                // 3、删除备件事务
                sparePartTransactionRecordDao.conditionDelete(null, consumeRecord.getId());
                // 4、删除报废记录
                scarpListDao.deleteByConsumingRecordId(id);
            }
        }
        return ids.length;
    }
}
